package pl.edu.agh.soa.monitoring.endpoints.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.jbi.management.DeploymentException;
import javax.jbi.messaging.ExchangeStatus;
import javax.jbi.messaging.MessageExchange;
import javax.jbi.messaging.NormalizedMessage;

import org.apache.log4j.Logger;
import org.apache.servicemix.common.Endpoint;
import org.apache.servicemix.common.endpoints.ProviderEndpoint;
import org.apache.servicemix.jbi.jaxp.SourceTransformer;
import org.apache.servicemix.jbi.jaxp.StringSource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.espertech.esper.client.EPStatementException;

import pl.edu.agh.soa.monitoring.endpoints.IReceiverEndpoint;
import pl.edu.agh.soa.monitoring.endpoints.IRegistrationEndpoint;

/**
 * @org.apache.xbean.XBean element="registrationEndpoint"
 */
public class RegistrationEndpoint extends ProviderEndpoint implements
		IRegistrationEndpoint {

	private final static Logger logger = Logger
			.getLogger(RegistrationEndpoint.class);

	IReceiverEndpoint receiverEndpoint;

	public void validate() throws DeploymentException {
	}

	@Override
	public void activate() {
		try {
			super.activate();
			for (Endpoint e : getServiceUnit().getEndpoints()) {
				if (e instanceof IReceiverEndpoint) {
					// we have found endpoint that have reference to esper
					// engine instance
					// we need to call registration operation on it
					receiverEndpoint = (IReceiverEndpoint) e;
				}
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	protected void processInOut(MessageExchange exchange, NormalizedMessage in,
			NormalizedMessage out) throws Exception {
		logger.info("Got message on exchange: " + exchange);

		if (exchange.getStatus() == ExchangeStatus.ACTIVE) {

			Object stmtObject = exchange.getProperty("stmt");
			String stmt = "";
			if (stmtObject != null) {
				stmt = (String) stmtObject;
			} else {
				out.setContent(new StringSource(
						"<warn>Statement not passed as property!</warn>"));
				logger.info("Statement not passed as property!");
				return;
			}
			Map<String, List<String>> callbackAddresses = parseCallbackAddressesList(new SourceTransformer()
					.toDOMDocument(in));
			try{
				receiverEndpoint.register(stmt, callbackAddresses);
				out.setContent(new StringSource(
				"<info>Successfully registered</info>"));
			}catch(EPStatementException e){
				if (e.getMessage().trim().startsWith("Failed to resolve event type:")){
					out.setContent(new StringSource(
					"<error>Nie odnaleziono zdarzenia o danym typie:" + e.getMessage().substring(e.getMessage().indexOf(":")) + "</error>"));
				}else{
					out.setContent(new StringSource(
							"<error>"+
							e.getMessage()+
							"</error>"));
				}
			}
			
			
		}
	}

	private Map<String, List<String>> parseCallbackAddressesList(
			Document doc) {
		Map<String, List<String>> callbackAddresses = new HashMap<String, List<String>>();

		NodeList addresses = doc.getElementsByTagName("address");
		for (int i = 0; i < addresses.getLength(); i++) {
			Element address = (Element) addresses.item(i);
			Node name = address.getElementsByTagName("name").item(0);
			String addressName = name.getTextContent();

			NodeList protocols = address.getElementsByTagName("protocol");
			List<String> protocolsValues = new ArrayList<String>();
			for (int j = 0; j < protocols.getLength(); j++) {
				Node protocol = protocols.item(j);
				protocolsValues.add(protocol.getTextContent());
			}
			callbackAddresses.put(addressName, protocolsValues);
		}

		return callbackAddresses;
	}

// TODO for test purposes
//	public static void main(String[] args) {
//		File file = new File("test.xml");
//		try {
//			DocumentBuilder builder = DocumentBuilderFactory.newInstance()
//					.newDocumentBuilder();
//			Document doc = builder.parse(file);
//			Map<String, List<String>> callbackAddresses = RegistrationEndpoint
//					.parseCallbackAddressesList(doc);
//			 for (String s : callbackAddresses.keySet()){
//			 System.out.println(s);
//			 for(String s2: callbackAddresses.get(s)){
//			 System.out.println("\t"+ s2);
//			 }
//			 }
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//
//	}
}
